#include "head.h"
// 用户信息-单链表的相关操作函数定义
// 单链表的创建
u_list *init_u_list(void)
{
    // 1 创建 头节点的动态空间
    u_list *list = (u_list *)malloc(sizeof(u_list));

    // 安全判断
    if (NULL == list)
    {
        printf("头结点创建失败!\n");
        return NULL;
    }
    // 如果成功则初始化链表中的头节点为 NULL
    list->next = NULL;
    return list;
}

// 单链表的销毁
void free_u_list(u_list **list)
{
    if (NULL == *list)
    {
        printf("表为NULL,无需销毁\n");
        return;
    }
    if (NULL == (*list)->next)
    {
        printf("表内数据为空,无需销毁\n");
        return;
    }

    // 1 销毁结点
    u_node *p1 = (*list)->next;
    u_node *p2 = p1->next;
    for (int i = 0; p1->next != NULL; i++)
    {
        free(p1);
        p1 = p2;
        // if 判断  判断 p2 = NULL 的时候 我们如何处理
        if (NULL != p2)
        {
            p2 = p2->next;
        }
    }
    // 2 销毁头结点
    free(*list);
    *list = NULL;
    return;
}

//  单链表的遍历
void print_u_list(u_list *list)
{
    // 判空
    IsEmpty_link_u_List(list);
    u_node *p = list->next; // 用于遍历
    printf("姓名\t\t密码\t\t性别\t\t等级\t\t手机号\t\t\t余额\t\t累计充值\n");
    printf("---------------------------------------------------------------------------------------------------------\n");
    while (p != NULL)
    {
        printf("%s\t\t%s\t\t%s\t\t%d\t\t%s\t\t\t%d\t\t%d\n",
               p->data.name, p->data.passwd, p->data.sex, p->data.level, p->data.phone,p->data.value,p->data.total_payment);
        p = p->next;
    }
    return;
}

// 打印一条用户数据
void print_one_udata(user_data data)
{
    printf("姓名\t\t密码\t\t性别\t\t等级\t\t手机号\t\t\t余额\t\t累计充值\n");
    printf("---------------------------------------------------------------------------------------------------------\n");
    printf("%s\t\t%s\t\t%s\t\t%d\t\t%s\t\t\t%d\t\t%d\n",
    data.name,data.passwd,data.sex,data.level,data.phone,data.value,data.total_payment);
    return;
}

// 单链表的判空
void IsEmpty_link_u_List(u_list *list)
{
    if (NULL == list)
    {
        printf("单链表为NULL!\n");
        return ;
    }
    if (list->next == NULL)
    {
        printf("单链表数据为空!\n");
        return ;
    }
    return ;
}

// 头插
void head_insert_u_node(u_list *list, user_data data)
{
    // 安全判断
    if (NULL == list)
    {
        ERRLOG("链表为NULL!");
        return;
    }
    // 生成新结点
    u_node *new_node = (u_node *)malloc(sizeof(u_node));
    if (NULL == new_node)
    {
        ERRLOG("创建新节点失败!");
        return;
    }
    // 写入数据
    new_node->data = data;
    // 新节点的next指向头结点的next
    new_node->next = list->next;
    // 头结点的next指向新节点
    list->next = new_node;
    return;
}

// 尾插保存到文件
void tail_insert_u_node(u_list *list, user_data data)
{

    // 生成一个新节点
    u_node *new = (u_node *)malloc(sizeof(u_node));
    // 特殊情况只有一个头结点,直接头插
    if (list->next == NULL)
    {
        head_insert_u_node(list, data);
        //写入到文件
        user_fprint_by_level(list,"w+");
        return;
    }

    u_node *p = list->next; // 用于遍历
    // 遍历至最后一个节点元素
    while (p->next != NULL)
    {
        p = p->next;
    }
    // 要插入的数据存放在新节点
    new->data = data;
    // 将新节点插入到链表尾部
    p->next = new;
    new->next = NULL; // 新节点结点置空
    // 写入到文件
    user_fprint_by_level(list, "w+");
    return;
}

// 尾插不保存到文件
void Tail_u_node(u_list *list, user_data data)
{
    // 生成一个新节点
    u_node *new = (u_node *)malloc(sizeof(u_node));
    // 特殊情况只有一个头结点,直接头插
    if (list->next == NULL)
    {
        head_insert_u_node(list, data);
        return;
    }

    u_node *p = list->next; // 用于遍历
    // 遍历至最后一个节点元素
    while (p->next != NULL)
    {
        p = p->next;
    }
    // 要插入的数据存放在新节点
    new->data = data;
    // 将新节点插入到链表尾部
    p->next = new;
    new->next = NULL; // 新节点结点置空
    return;
}
// 单链表的查找
u_node *find_u_node_id(u_list *list, int pos)
{
    // 安全判断
    IsEmpty_link_u_List(list);
    u_node *p = list->next;
    int loc = 1; // 用于记录结点的当前位置
    // 遍历找到p的位置
    while (p && (loc != pos)) // p非空和loc没有到指定位置(注意是与,一假即假)
    {
        p = p->next;
        loc++;
    }
    // 安全判断
    if (!p && loc > pos) // p为空,或者 位置不合法pos＞n或pos<=0 直接返回NULL
    {
        // printf("查找的位置非法!\n");
        return NULL;
    }
    // 返回第pos个结点的指针
    return p;
}

// 按值查找
u_node *find_u_node_name(u_list *list, char *name)
{
    // 安全判断
    IsEmpty_link_u_List(list);
    u_node *p = list->next;
    while (strcmp(p->data.name, name))
    {
        p = p->next;
        if (p == NULL)
        {
            // text_center("抱歉,查无此人!\n",RED);
            return NULL;
        }
    }
    return p;
}

// 按名字查找返回节点数据
user_data find_u_data_name(u_list *list, char *name)
{
    user_data data;
    // 安全判断
    IsEmpty_link_u_List(list);
    u_node *p = list->next;
    while (strcmp(p->data.name, name))
    {
        p = p->next;
        if (p == NULL)
        {
            text_center("抱歉,查无此人!\n", RED);
            return data;
        }
    }
    data = p->data;
    return data;
}


// 按名字删除
void delete_u_node_byname(u_list *list, char *name)
{
  
    // 安全判断
    IsEmpty_link_u_List(list);
    int pos = 1;            // 按值查找对应位置
    u_node *p = list->next;
    while (strcmp(p->data.name, name))
    {
        p = p->next;
        pos++;
        if (p == NULL)
        {
            text_center("抱歉,查无此人!\n", RED);
            return ;
        }
    }
    //删除对应的结点
    delete_u_node(list,pos);
    //写入到文件
    user_fprint_by_level(list,"w+");
    return;
}

// 任意插
void insert_u_node(u_list *list, user_data data, int pos)
{
    // 安全判断
    if (NULL == list)
    {
        printf("链表为NULL!\n");
        return;
    }
    // 生成新结点
    u_node *new_node = (u_node *)malloc(sizeof(u_node));

    // 插到头结点后或者只有一个头结点的情况,直接头插
    if (pos == 1 || NULL == list->next)
    {
        new_node->data = data;       // 赋值
        new_node->next = list->next; // 将新节点链接到头结点的后一位
        list->next = new_node;       // 将新节点链接上
        return;
    }

    // 先找到插入位置的前一个结点
    u_node *p = find_u_node_id(list, pos - 1);
    // 插入的位置有误,则释放新节点
    if (NULL == p)
    {
        printf("插入的位置非法!\n");
        free(new_node); // 释放新节点
        return;
    }

    new_node->data = data;    // 赋值
    new_node->next = p->next; // 将新节点链接到p结点的后一位
    p->next = new_node;       // 将新节点链接上
    return;
}

// 尾删
void tail_delete_u_node(u_list *list)
{
    // 安全判断
    IsEmpty_link_u_List(list);
    // 特殊情况只有一个头结点
    if (list->next == NULL)
    {
        // 头结点置空
        // free(list);
        // list = NULL;
        printf("表内已无数据!\n");
        return;
    }
    u_node *p = list->next; // 用于遍历
    u_node *del = p->next;  // 用于删除最后一个结点
    // 遍历至最后一个节点元素前一个结点
    while (del->next != NULL)
    {
        p = p->next;
        del = del->next;
    }
    // 删除最后一个结点
    p->next = NULL;
    free(del);
    del = NULL;
}

// 任意删除
void delete_u_node(u_list *list, int pos)
{
    // 安全判断
    if (NULL == list)
    {
        printf("链表为NULL!\n");
        return;
    }

    // 只有一个头结点的情况
    if (NULL == list->next)
    {
        printf("链表内数据已为空,无法删除!\n");
        return;
    }
    // 接收删除的结点
    u_node *del_p = NULL;

    // 删除的是第一个元素
    if (pos == 1)
    {
        del_p = list->next;
        list->next = del_p->next; // 改指向
        // 释放删除的结点
        free(del_p);
        return;
    }

    // 先找到删除位置的前一个结点
    u_node *p = find_u_node_id(list, pos - 1);

    // 删除的位置有误,则释放新节点
    if (p == NULL || NULL == p->next) // 要用或判断，一真即真!
    {
        printf("删除的位置非法!\n");
        return;
    }

    del_p = p->next;       // 临时保存被删结点的地址以备释放
    p->next = del_p->next; // 改指向
    free(del_p);           // 释放删除的结点
    return;
}

// 单链表的清空
void clear_u_list(u_list *list)
{
    // 安全判断
    IsEmpty_link_u_List(list);
    // 1 销毁结点
    u_node *p1 = (list)->next;
    u_node *p2 = p1->next;
    for (int i = 0; p1->next != NULL; i++)
    {
        free(p1);
        p1 = p2;
        // if 判断  判断 p2 = NULL 的时候 我们如何处理
        if (NULL != p2)
        {
            p2 = p2->next;
        }
    }
    list->next = NULL;
    return;
    // 不需要销毁头结点
}

// 单链表的合并
u_list *merge_link_lists(u_list *list1, u_list *list2)
{
    //安全判断
    if (NULL == list1 || NULL == list2)
    {
        printf("表1或表2为NULL!\n");
        return NULL;
    }

    // 用于遍历List2
    u_node *p = list2->next;
    while (p != NULL)
    {
        //尾插,将list2中的数据依次复制到list1中
        Tail_u_node(list1, p->data);
        p = p->next;
    }
    //返回合并后的链表
    return list1;
}

